Skip to content

DataGrid - Fix the browser scrolling back to the grid when data is updated (T1310557)#33168

Open
markallenramirez wants to merge 7 commits intoDevExpress:26_1from
markallenramirez:bug_T1310557/26_1
Open

DataGrid - Fix the browser scrolling back to the grid when data is updated (T1310557)#33168
markallenramirez wants to merge 7 commits intoDevExpress:26_1from
markallenramirez:bug_T1310557/26_1

Conversation

@markallenramirez
Copy link
Copy Markdown
Contributor

No description provided.

@markallenramirez markallenramirez self-assigned this Apr 6, 2026
Copilot AI review requested due to automatic review settings April 6, 2026 12:56
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Fixes DataGrid keyboard-navigation focus restoration so that updating data doesn’t cause the browser to scroll the page back to the grid (by using native focus({ preventScroll }) during render completion).

Changes:

  • Add a preventScroll flag to _updateFocus and _focus and propagate it from renderCompleted.
  • Replace synthetic eventsEngine.trigger(..., 'focus') with native DOM focus({ preventScroll }) for the focused cell/row.

@markallenramirez markallenramirez requested a review from a team as a code owner April 7, 2026 08:51
Copilot AI review requested due to automatic review settings April 7, 2026 08:55
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

Copilot AI review requested due to automatic review settings April 8, 2026 09:04
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.

Copilot AI review requested due to automatic review settings April 8, 2026 12:36
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.

Comment on lines +4996 to +5063
$('body').css('height', 2000);
window.scrollTo(0, 0);
this.clock.tick(10);

const keyboardController = dataGrid.getController('keyboardNavigation');
const $firstCell = $(dataGrid.getCellElement(0, 0));
const scrollPosition = 300;

// assert
assert.strictEqual(window.pageYOffset, 0, 'document scroll is at the top');

// act
$firstCell.trigger(CLICK_EVENT);
this.clock.tick(10);

keyboardController.keyDownHandler({
key: 'Tab',
keyName: 'tab',
originalEvent: $.Event('keydown', { target: $firstCell.get(0) }),
});
this.clock.tick(10);

// assert
assert.ok($(dataGrid.getCellElement(0, 1)).hasClass('dx-focused'), 'second cell is focused');

// act
window.scrollTo(0, scrollPosition);

// assert
assert.strictEqual(window.pageYOffset, scrollPosition, 'document scroll is changed');

// act
dataGrid.getDataSource().store().push([{ type: 'update', key: 1, data: { name: 'updated' } }]);
this.clock.tick(10);

// assert
assert.strictEqual($(dataGrid.getCellElement(0, 1)).text(), 'updated', 'second cell text is updated');
assert.strictEqual(window.pageYOffset, scrollPosition, 'document scroll is preserved after push update');

// act
dataGrid.refresh();
this.clock.tick(10);

// assert
assert.strictEqual(window.pageYOffset, scrollPosition, 'document scroll is preserved after refresh');

// act
dataGrid.repaint();
this.clock.tick(10);

// assert
assert.strictEqual(window.pageYOffset, scrollPosition, 'document scroll is preserved after repaint');

// act
keyboardController.keyDownHandler({
key: 'ArrowLeft',
keyName: 'leftArrow',
originalEvent: $.Event('keydown', { target: $(dataGrid.getCellElement(0, 1)).get(0) }),
});
this.clock.tick(10);

// assert
assert.ok($(dataGrid.getCellElement(0, 0)).hasClass('dx-focused'), 'first cell is focused');
assert.strictEqual(window.pageYOffset, 0, 'document scroll is changed after keyboard navigation');

// cleanup
$('body').css('height', '');
window.scrollTo(0, 0);
Copy link

Copilot AI Apr 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test mutates global page state (body height and window scroll position) without a try/finally-style guard. If an exception occurs before the cleanup section, subsequent tests can run with a modified document height/scroll position. Consider capturing the initial body height/scroll position and restoring them in a finally block (or using an appended temporary spacer element like other scrolling-related tests do).

Suggested change
$('body').css('height', 2000);
window.scrollTo(0, 0);
this.clock.tick(10);
const keyboardController = dataGrid.getController('keyboardNavigation');
const $firstCell = $(dataGrid.getCellElement(0, 0));
const scrollPosition = 300;
// assert
assert.strictEqual(window.pageYOffset, 0, 'document scroll is at the top');
// act
$firstCell.trigger(CLICK_EVENT);
this.clock.tick(10);
keyboardController.keyDownHandler({
key: 'Tab',
keyName: 'tab',
originalEvent: $.Event('keydown', { target: $firstCell.get(0) }),
});
this.clock.tick(10);
// assert
assert.ok($(dataGrid.getCellElement(0, 1)).hasClass('dx-focused'), 'second cell is focused');
// act
window.scrollTo(0, scrollPosition);
// assert
assert.strictEqual(window.pageYOffset, scrollPosition, 'document scroll is changed');
// act
dataGrid.getDataSource().store().push([{ type: 'update', key: 1, data: { name: 'updated' } }]);
this.clock.tick(10);
// assert
assert.strictEqual($(dataGrid.getCellElement(0, 1)).text(), 'updated', 'second cell text is updated');
assert.strictEqual(window.pageYOffset, scrollPosition, 'document scroll is preserved after push update');
// act
dataGrid.refresh();
this.clock.tick(10);
// assert
assert.strictEqual(window.pageYOffset, scrollPosition, 'document scroll is preserved after refresh');
// act
dataGrid.repaint();
this.clock.tick(10);
// assert
assert.strictEqual(window.pageYOffset, scrollPosition, 'document scroll is preserved after repaint');
// act
keyboardController.keyDownHandler({
key: 'ArrowLeft',
keyName: 'leftArrow',
originalEvent: $.Event('keydown', { target: $(dataGrid.getCellElement(0, 1)).get(0) }),
});
this.clock.tick(10);
// assert
assert.ok($(dataGrid.getCellElement(0, 0)).hasClass('dx-focused'), 'first cell is focused');
assert.strictEqual(window.pageYOffset, 0, 'document scroll is changed after keyboard navigation');
// cleanup
$('body').css('height', '');
window.scrollTo(0, 0);
const $body = $('body');
const initialBodyHeight = $body.css('height');
const initialScrollLeft = window.pageXOffset;
const initialScrollTop = window.pageYOffset;
$body.css('height', 2000);
window.scrollTo(0, 0);
this.clock.tick(10);
try {
const keyboardController = dataGrid.getController('keyboardNavigation');
const $firstCell = $(dataGrid.getCellElement(0, 0));
const scrollPosition = 300;
// assert
assert.strictEqual(window.pageYOffset, 0, 'document scroll is at the top');
// act
$firstCell.trigger(CLICK_EVENT);
this.clock.tick(10);
keyboardController.keyDownHandler({
key: 'Tab',
keyName: 'tab',
originalEvent: $.Event('keydown', { target: $firstCell.get(0) }),
});
this.clock.tick(10);
// assert
assert.ok($(dataGrid.getCellElement(0, 1)).hasClass('dx-focused'), 'second cell is focused');
// act
window.scrollTo(0, scrollPosition);
// assert
assert.strictEqual(window.pageYOffset, scrollPosition, 'document scroll is changed');
// act
dataGrid.getDataSource().store().push([{ type: 'update', key: 1, data: { name: 'updated' } }]);
this.clock.tick(10);
// assert
assert.strictEqual($(dataGrid.getCellElement(0, 1)).text(), 'updated', 'second cell text is updated');
assert.strictEqual(window.pageYOffset, scrollPosition, 'document scroll is preserved after push update');
// act
dataGrid.refresh();
this.clock.tick(10);
// assert
assert.strictEqual(window.pageYOffset, scrollPosition, 'document scroll is preserved after refresh');
// act
dataGrid.repaint();
this.clock.tick(10);
// assert
assert.strictEqual(window.pageYOffset, scrollPosition, 'document scroll is preserved after repaint');
// act
keyboardController.keyDownHandler({
key: 'ArrowLeft',
keyName: 'leftArrow',
originalEvent: $.Event('keydown', { target: $(dataGrid.getCellElement(0, 1)).get(0) }),
});
this.clock.tick(10);
// assert
assert.ok($(dataGrid.getCellElement(0, 0)).hasClass('dx-focused'), 'first cell is focused');
assert.strictEqual(window.pageYOffset, 0, 'document scroll is changed after keyboard navigation');
} finally {
$body.css('height', initialBodyHeight);
window.scrollTo(initialScrollLeft, initialScrollTop);
}

Copilot uses AI. Check for mistakes.
Comment on lines +4984 to +4986
// T1310557
QUnit.testInActiveWindow('Browser should not scroll back to the grid when a focused cell is updated or rerendered', function(assert) {
// arrange
Copy link

Copilot AI Apr 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This scrolling/focus regression test is currently placed under the "Column Resizing" module, but it doesn't exercise resizing behavior. Moving it to a more relevant module (e.g., "View's focus" or a dedicated scrolling/focus module) will make the suite easier to navigate and maintain.

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants